package books.in_action.lambda

data class Person(val age: Int, val name: String)

fun main(args: Array<String>) {

    //定义一个lambda表达式 {参数 -> 表达式}
    val sum = { num1: Int, num2: Int -> num1 + num2 }
    println(sum(1, 2))

    //调用 {参数 -> 表达式}() ，无参可省略 ，->可省略
//    { num1: Int, num2: Int -> num1 + num2 }(1,3).also(::println)
//    { println(42)}(1)

    //lambda表达式作为参数,这里用了类型推导 person:Person -> person.name
    val people = listOf(Person(1, "Alice"), Person(23, "Bob"))
    //做字符的逐一比较
    people.maxBy({ person -> person.name }).also(::println)
    //如果函数最后一个参数是lambda，可以将{}放到()外面
    people.maxBy() { person -> person.name }.also(::println)
    //如果只有一个lambda作为参数，()可省略
    people.maxBy { person -> person.name }.also(::println)
    //默认参数it代替隐式实参
    people.maxBy { it.name }.also(::println)
    //Person::name ,成员引用，相当于 person:Person -> person.name
    people.maxBy(Person::name).also(::println)

    //如果用变量替代lambda ，it 和类型推导不能使用
    val maxOf = { person: Person -> person.name }
    people.maxBy(maxOf).also(::println)

    //拼接集合每一个元素
    people.joinToString(",") { it.name }.also(::println)

    //函数的引用,::hello相当于()->Unit
    run(::hello)

    //类的引用,将创建类的实例的动作保存成值延迟创建
    val createPerson = ::Person
    val person = createPerson(3, "孤独时代")
    println(person)

    //扩展函数的引用，与类成员函数引用一样，(Person::isAdult)(p) == p:Person -> Boolean
    println((person::isAdult)())  //1.1 以后支持
    println((Person::isAdult)(people[1]))

}

fun hello() = println("hello")

fun Person.isAdult() = age >= 21


